package server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.security.KeyStore;

import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.security.cert.X509Certificate;

import constants.Cmd;
import constants.Log;

public class Server {
	 private ControlList controlList;
	 private int port;
	 private BufferedReader br;
	 private BufferedWriter bw;
	 private String accessRight;
	 private  OutputStream out;
	 private InputMasterServer inputMaster;
	 private RecordCollection rc;
	 private String subjectName;
	 private static final String keypass="password";
	 private Log log;
	public Server(int port){
		controlList=new ControlList();
		rc=new RecordCollection(controlList);
		this.port=port;
	}
	public void startServer() throws IOException{
		 SSLServerSocketFactory ssocketFactory = null;
	        try {
	        	SSLContext ctx;
	        	KeyManagerFactory kmf;
	        	KeyStore ks;
	        	char[] passphrase = keypass.toCharArray();
	        	ctx = SSLContext.getInstance("TLS");
	        	kmf = KeyManagerFactory.getInstance("SunX509");
	        	ks = KeyStore.getInstance("JKS");
	        	ks.load(new FileInputStream("serverKeystore.jks"), passphrase);
	        	kmf.init(ks, passphrase);
	        	ctx.init(kmf.getKeyManagers(), null, null);
	        	ssocketFactory = ctx.getServerSocketFactory();
	        } catch (Exception e) {
	        	throw new IOException(e.getMessage());
	        }        
		SSLServerSocket ssocket = (SSLServerSocket) ssocketFactory.createServerSocket(port);
		ssocket.setNeedClientAuth(true);
		SSLSocket socket = (SSLSocket) ssocket.accept();
		//Fixa input och outputstream
	    InputStream in = socket.getInputStream();
        InputStreamReader inReader = new InputStreamReader(in);
        br = new BufferedReader(inReader);
        out = socket.getOutputStream();
		OutputStreamWriter outputstreamwriter = new OutputStreamWriter(out);
        bw = new BufferedWriter(outputstreamwriter);
        inputMaster=new InputMasterServer(br, this, log);
        //Kolla cert
        SSLSession session = socket.getSession();
        X509Certificate cert = (X509Certificate) session.getPeerCertificateChain()[0];
        accessRight=this.getAccessRight(cert);
        toClient(accessRight+"\n");
       
        inputMaster.start();
	}
	private String getAccessRight(X509Certificate cert) {
		 String subjectString = cert.getSubjectDN().getName();
			String[] subjectStringArray=subjectString.split("=");
			subjectString=subjectStringArray[1];
			subjectStringArray=subjectString.split(",");
			subjectString=subjectStringArray[subjectStringArray.length-2];
			subjectName=subjectString;
		return controlList.getAccessRights(subjectString);
	}
	public void newInput(String fromClient){
		System.out.println("From Client: "+ fromClient);
		
		 //Skapa record
		if(fromClient.startsWith(Cmd.newRecord)){
			//rc.addRecord(new Record(fromClient+"#"+subjectName),subjectName);
			rc.addRecord(fromClient, subjectName);
		}
		// LÄGG TILL SÅ ATT VILKEN NURSE ELLER DOCTOR SOM HELST PÅ SAMMA SJUKHUS HAR TILLGÅNG
		//L�s record
		else if(fromClient.startsWith(Cmd.readRecord)||fromClient.startsWith(Cmd.readSubjectsRecord)){ 
			String returnRecord;
			if(fromClient.startsWith(Cmd.readSubjectsRecord)){
				returnRecord=rc.getRecord(fromClient.substring(Cmd.readSubjectsRecord.length())+subjectName,subjectName);
			}else{
				returnRecord=rc.getRecord(fromClient.substring(Cmd.readRecord.length()),subjectName);
			}
			if(returnRecord!=null){
				toClient(Cmd.readRecord+returnRecord);
				toClient(Cmd.success);
			}else{
				toClient(Cmd.error);
			}
		}
		//Edit record
		else if(fromClient.startsWith(Cmd.editRecord)){
			if(rc.editRecord(fromClient.substring(Cmd.editRecord.length()),subjectName)){
				toClient(Cmd.success);
			}else{
				toClient(Cmd.error);
			}
			//delete rec
		}else if(fromClient.startsWith(Cmd.delete)){
			if(rc.delRecord(fromClient.substring(Cmd.delete.length()),subjectName)){
				toClient(Cmd.success);
			}else{
				toClient(Cmd.error);
			}
		}
	}
	private void toClient(String message){
		try {
			bw.write(message+"\n");
			bw.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
